package org.example.springnetty.MyNetty.echo;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LineBasedFrameDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;

/**
 * 基于Netty的服务器
 */

public class EchoServer {
    private static final Logger log = LoggerFactory.getLogger(EchoServer.class);
    private final int port;
    public EchoServer(int port) {this.port = port;}

    public static void main(String[] args) throws InterruptedException {
        int port = 9999;
        EchoServer server = new EchoServer(port);
        log.info("服务器即将启动");
        server.start();
        log.info("服务器关闭");

    }
    public void start() throws InterruptedException {
        /*线程组*/
        EventLoopGroup boss = new NioEventLoopGroup();
        EventLoopGroup work = new NioEventLoopGroup();
        try{
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(boss,work)
                    .channel(NioServerSocketChannel.class)//指定使用NIO的通信模式-》jdk
//                    .channel(EpollServerSocketChannel.class)//指定使用Epoll的通信模式-》Linux
//                    .option(ChannelOption.SO_BACKLOG,1024)//连接数（已完成三次握手）
//                    .option(ChannelOption.SO_REUSEADDR,true)//重用time_wait时期ip和端口（子网或多网卡情况使用）
//                    .option(ChannelOption.SO_KEEPALIVE,true)//两小时内没有数据的通信时，TCP 会自动发送一个活动探测数据报文。
//                    .option(ChannelOption.SO_LINGER,2)//阻塞close()的调用时间，直到数据完全发送
//                    .option(ChannelOption.TCP_NODELAY,true)//不论TCP报文大小，立马发送
                    .localAddress(new InetSocketAddress(port))
//                    .childOption(ChannelOption.SO_RCVBUF)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
//                            socketChannel.pipeline().addLast(new ServerOutReadHandler());
//                            socketChannel.pipeline().addLast(new MessageCountHandler());
//                            socketChannel.pipeline().addLast(new LengthFieldBasedFrameDecoder(1024,0,4,0,0));
                            socketChannel.pipeline().addLast(new LineBasedFrameDecoder(1024*5));
                            socketChannel.pipeline().addLast(new EchoServerHandler());
                        }
                    });
            /*异步绑定到服务器,sync()会阻塞到完成*/
            ChannelFuture future = bootstrap.bind().sync();
            System.out.println("服务器启动完成，等待客户端的连接和数据.....");
            /*阻塞当前线程,直到服务器的serverChannel被关闭 */
            future.channel().closeFuture().sync();

        }finally {
            boss.shutdownGracefully().sync();
            work.shutdownGracefully().sync();
        }
    }
}
